﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Openlab.Tools.CodeGender.Funtions;
using CarolLib.Tools.CodeGender;

namespace Openlab.Tools.CodeGender.Classes
{
    public class ManagerClass : Class
    {
        string entityClass;
        Column idColumn;
        CodeOption option;
        public ManagerClass(CodeOption option)
            : base(option.ManagerClassName, option.BllNamespaceName)
        {
            this.option = option;
            entityClass = option.ClassName;
            idColumn = option.IdColumn;
            WithDefaultConstructor = false;
            ClassType = option.IsBllSinglon ? string.Empty : "static";

            ClassType += option.IsPartial ? " partial" : string.Empty;

            ParentClass = option.ParentClass;
        }

        public override string Body
        {
            get
            {
                StringBuilder code = new StringBuilder();


                code.AppendFormat("#region {0}", entityClass);
                code.AppendLine();
                code.AppendLine();

                if (option.IsBllSinglon)
                {
                    #region Singleton

                    code.AppendLine("#region Singleton");
                    code.AppendLine();

                    code.AppendLine(GetSingletonCode());
                    code.AppendLine();

                    code.AppendLine("#endregion");


                    #endregion
                }

                #region 缓存

                code.AppendLine("#region 实体缓存");
                code.AppendLine();

                code.AppendLine(GetCacheCode());
                code.AppendLine();

                code.AppendLine("#endregion");

                #endregion

                #region 从缓存读取

                FunctionOption funcOptionGetEntitySet = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                //funcOption.EntityClass = entityClass;
                //funcOption.FunctionName = GetIdsFuncName;
                //funcOption.FunctionName2 = GetEntitiesFuncName;
                //funcOption.EntityCacheName = EntitiesCacheName;
                //funcOption.IdColumn = idColumn;
                //funcOption.DalClass = option.DalClassName;

                //funcOption.IsBat = false;
                //funcOption.IsBllSingleton = option.IsBllSinglon;
                //funcOption.IsPartial = option.IsPartial;
                //funcOption.WithTran=false;

                funcOptionGetEntitySet.FunctionName = GetEntitiesFuncName;
                funcOptionGetEntitySet.FunctionName2 = GetIdsFuncName;
                funcOptionGetEntitySet.ReturnType = option.IsBllSinglon ? string.Format("PagedResult<{0}>", entityClass) : string.Format("static PagedResult<{0}>", entityClass);
                Function funcGetEntitySet = new GetEntitySetFunc(funcOptionGetEntitySet);

                FunctionOption funcOptionGetEntities = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                funcOptionGetEntities.FunctionName = GetEntitiesFuncName;
                funcOptionGetEntities.ReturnType = option.IsBllSinglon ? string.Format("List<{0}>", entityClass) : string.Format("static List<{0}>", entityClass);
                Function funcGetEntities = new GetEntitiesFunc(funcOptionGetEntities);

                FunctionOption funcOptionGetEntity = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                funcOptionGetEntity.FunctionName = GetEntitiesFuncName;
                funcOptionGetEntity.ReturnType = option.IsBllSinglon ? string.Format(entityClass) : string.Format("static {0}", entityClass);
                Function funcGetEntity = new GetEntityFunc(funcOptionGetEntity);

                FunctionOption funcOptionCreateEntity = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                funcOptionCreateEntity.FunctionName = CreateFuncName;
                funcOptionCreateEntity.ReturnType = option.IsBllSinglon ? string.Format(entityClass) : string.Format("static {0}", entityClass);
                Function funcCreatEntity = new CreateEntityFunc(funcOptionCreateEntity);

                FunctionOption funcOptionDeleteEntity = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                funcOptionDeleteEntity.FunctionName = DeleteEntityFuncName;
                funcOptionDeleteEntity.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                Function funcDeleteEntity = new DeleteEntityFunc(funcOptionDeleteEntity);

                FunctionOption funcOptionUpdateEntity = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                funcOptionUpdateEntity.FunctionName = UpdateEntityFuncName;
                funcOptionUpdateEntity.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                Function funcUpdateEntity = new UpdateEntityFunc(funcOptionUpdateEntity);



                code.AppendLine("#region 实体查找");
                code.AppendLine();

                code.AppendLine(funcGetEntity.Code);
                code.AppendLine();

                code.AppendLine(funcGetEntities.Code);
                code.AppendLine();

                code.AppendLine(funcGetEntitySet.Code);
                code.AppendLine();

                code.AppendLine("#endregion");
                code.AppendLine();
                code.AppendLine();


                #endregion

                #region 写操作
                code.AppendLine("#region 写操作");
                code.AppendLine();

                code.AppendLine(funcCreatEntity.Code);
                code.AppendLine();

                if (option.CreateBatOperation)
                {
                    FunctionOption funcOptionCreateBat = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                    funcOptionCreateBat.IsBat = true;
                    funcOptionCreateBat.FunctionName = CreateFuncName;
                    funcOptionCreateBat.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                    Function funcCreateBat = new CreateEntityFunc(funcOptionCreateBat);
                    code.AppendLine(funcCreateBat.Code);
                    code.AppendLine();
                }

                code.AppendLine(funcDeleteEntity.Code);
                code.AppendLine();


                code.AppendLine(funcUpdateEntity.Code);
                code.AppendLine();

                //if (option.CreateBatOperation)
                //{
                //    FunctionOption funcOptionUpdateBat = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, false);
                //    funcOptionUpdateBat.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                //    funcOptionUpdateBat.IsBat = true;
                //    funcOptionUpdateBat.FunctionName = UpdateEntityFuncName;
                //    Function funcUpdateBat = new UpdateEntityFunc(funcOptionUpdateBat);
                //    code.AppendLine(funcUpdateBat.Code);
                //    code.AppendLine();
                //}




                if (option.WithTrans)
                {

                    code.AppendLine("#region 带事务的写操作");
                    code.AppendLine();

                    FunctionOption funcOptionCreatEntityTran = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, true);
                    funcOptionCreatEntityTran.ReturnType = option.IsBllSinglon ? string.Format(entityClass) : string.Format("static {0}", entityClass);
                    funcOptionCreatEntityTran.IsBat = false;
                    funcOptionCreatEntityTran.FunctionName = CreateFuncName;
                    Function funcCreatEntityTran = new CreateEntityFunc(funcOptionCreatEntityTran);
                    code.AppendLine(funcCreatEntityTran.Code);
                    code.AppendLine();

                    if (option.CreateBatOperation)
                    {
                        FunctionOption funcOptionCreatEntityTranbat = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, true);
                        funcOptionCreatEntityTranbat.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                        funcOptionCreatEntityTranbat.IsBat = true;
                        funcOptionCreatEntityTranbat.FunctionName = CreateFuncName;
                        Function funcCreateBatTran = new CreateEntityFunc(funcOptionCreatEntityTranbat);
                        code.AppendLine(funcCreateBatTran.Code);
                        code.AppendLine();
                    }


                    FunctionOption funcOptionDeleteEntityTran = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, true);
                    funcOptionDeleteEntityTran.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                    funcOptionDeleteEntityTran.IsBat = false;
                    funcOptionDeleteEntityTran.FunctionName = DeleteEntityFuncName;
                    Function funcDeleteEntityTran = new DeleteEntityFunc(funcOptionDeleteEntityTran);
                    code.AppendLine(funcDeleteEntityTran.Code);
                    code.AppendLine();


                    FunctionOption funcOptionUpdateEntityTran = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, true);
                    funcOptionUpdateEntityTran.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                    funcOptionUpdateEntityTran.IsBat = false;
                    funcOptionUpdateEntityTran.FunctionName = UpdateEntityFuncName;
                    Function funcUpdateEntityTran = new UpdateEntityFunc(funcOptionUpdateEntityTran);
                    code.AppendLine(funcUpdateEntityTran.Code);
                    code.AppendLine();

                    //if (option.CreateBatOperation)
                    //{
                    //    FunctionOption funcOptionUpdateBatTran = new FunctionOption(entityClass, EntitiesCacheName, idColumn, option.DalClassName, false, option.IsBllSinglon, option.IsPartial, true);
                    //    funcOptionUpdateBatTran.ReturnType = option.IsBllSinglon ? string.Format("bool") : string.Format("static bool");
                    //    funcOptionUpdateBatTran.IsBat = true;
                    //    funcOptionUpdateBatTran.FunctionName = UpdateEntityFuncName;
                    //    Function funcUpdateBat = new UpdateEntityFunc(funcOptionUpdateBatTran);
                    //    code.AppendLine(funcUpdateBat.Code);
                    //    code.AppendLine();
                    //}

                    code.AppendLine("#endregion");
                    code.AppendLine();
                }

                #endregion

                code.AppendLine("#endregion");
                code.AppendLine();

                code.AppendLine("#endregion");

                return code.ToString();
            }
        }

        string GetCacheCode()
        {
            StringBuilder code = new StringBuilder();
            string paramEntities = PluralizerHelper.ToPlural(entityClass.ToFirstLower()) + "Cache";
            code.AppendLineFormatWithTabs("static CacheEntityTable<{0}, {1}> {2} = CacheManager.GetCacheEntityTable<{0}, {1}>(\"{2}\", 180, 10000);", 0
                , idColumn.CSTypeName, entityClass, paramEntities);
            code.AppendLineFormatWithTabs("public static CacheEntityTable<{0}, {1}> {2}", 0
                , idColumn.CSTypeName, entityClass, paramEntities.ToFirstUpper());
            code.AppendLineWithTabs("{", 0);
            code.AppendLineFormatWithTabs("get {{ return {0}; }}", 1, paramEntities);
            code.AppendLineFormatWithTabs("set {{ {0} = value; }}", 1, paramEntities);
            code.AppendLineWithTabs("}", 0);
            return code.ToString();
        }

        string GetSingletonCode()
        {
            return string.Format("public static readonly {0} Instance=new {0}();\n\r\nprivate {0}(){{}}", option.ManagerClassName);
        }

        string GetIdsFuncName
        {
            get
            {
                return string.Format("Get{1}{0}", idColumn.Name.ToPlural(), entityClass);
            }
        }

        string GetEntitiesFuncName
        {
            get
            {
                return string.Format("Get{0}", PluralizerHelper.ToPlural(entityClass));
            }
        }

        string EntitiesCacheName
        {
            get
            {
                return string.Format("{0}Cache", PluralizerHelper.ToPlural(entityClass));
            }
        }

        string CreateFuncName
        {
            get
            {
                // return string.Format("Create{0}", PluralizerHelper.ToPlural(entityClass));
                return string.Format("Create{0}", entityClass);
            }
        }
        string DeleteEntityFuncName
        {
            get
            {
                // return string.Format("Delete{0}", PluralizerHelper.ToPlural(entityClass));
                return string.Format("Delete{0}", entityClass);
            }
        }
        string UpdateEntityFuncName
        {
            get
            {
                return string.Format("Update{0}", entityClass);
                //return string.Format("Update{0}", PluralizerHelper.ToPlural(entityClass));
            }
        }
    }
}
